﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SdmxMl.Structure;
using SdmxMl.Common;
using SdmxMl.Excel;

namespace SasPlugIn.Table
{
    public class ConceptSchemeArtefactTable : BaseSasTable
    {
         /// <summary>The artefact to transform in SAS instructions for table creation</summary>
        private ConceptSchemeType cScheme;

        /// <summary>
        /// C'tor for generation of a SAS table holding codelists artefact Information
        /// </summary>
        /// <param name="conceptSchemeArtefact">an object of Artefact type</param>
        /// <param name="anInv">inventory of selected annotations to place in table</param>
        /// <param name="prefix">Prefix for sas table</param>
        public ConceptSchemeArtefactTable(ConceptSchemeType conceptSchemeArtefact, AnnotationInventory anInv, string prefix)
            : base(conceptSchemeArtefact, "", prefix) 
        {
            cScheme = conceptSchemeArtefact;
            anInventory = anInv;
            header.Name = DefaultTableName(cScheme);
            FillHeader();
        }

        /// <summary>
        /// C'tor for generation of a SAS table holding codelists artefact Information
        /// </summary>
        /// <param name="conceptSchemeArtefact">an object of Artefact type</param>
        /// <param name="anInv">inventory of selected annotations to place in table</param>
        /// <param name="tableName">Name of Sas table</param>
        /// <param name="prefix">Prefix for sas table</param>
        public ConceptSchemeArtefactTable(ConceptSchemeType conceptSchemeArtefact, AnnotationInventory anInv, string tableName, string prefix)
            : base(conceptSchemeArtefact, tableName, prefix)
        {
            cScheme = conceptSchemeArtefact;
            anInventory = anInv;
            FillHeader();
        }

        public static string DefaultTableName(ConceptSchemeType conceptScheme)
        {
            return conceptScheme.Id.StartsWith("CS_") ? conceptScheme.Id.Substring(3) : conceptScheme.Id;
        }

        /// <summary>
        /// Fill Header columns according to artefact attributes
        /// </summary>
        protected override void FillHeader()
        {
            TextFormatType tft = new TextFormatType();
            tft.TextType = TextTypeType.String;
            tft.maxLength = ID_DEFAULT_LEN.ToString();

            TextFormatType tftLevel = new TextFormatType();
            tftLevel.TextType = TextTypeType.Integer;
            tftLevel.maxLength = "2";

            header.Add(new HeaderColumn(CODE_COL_NAME, tft));
            header.Add(new HeaderColumn(PARENT_COL_NAME, tft));
            header.Add(new HeaderColumn(LEVEL_COL_NAME, tftLevel));

            foreach (string lg in LangSupport.SupportedLanguages)
                header.Add(new HeaderColumn(INTERNATIONALIZED_NAME_PREFIX + lg, NAME_DEFAULT_LEN));

            foreach (string lg in LangSupport.SupportedLanguages)
                header.Add(new HeaderColumn(INTERNATIONALIZED_DESCR_PREFIX + lg, DESCRIPTION_DEFAULT_LEN));

            //header.Add(new HeaderColumn("ValidFrom", 10));
            //header.Add(new HeaderColumn("ValidTo", 10));

            // here Annotations selected
            GenAnnotationHeader();
        }

        protected override void GenerateDataRows(StringBuilder sb)
        {
            foreach (ConceptType c in cScheme.ConceptList)
            {
                List<string> rowValues = PrepareRowDatas(c);
                // Create instruction
                header.GenerateInsertTableInstructions(sb, rowValues.AsReadOnly());
            }
        }

        protected override List<string> PrepareRowDatas(object o)
        {
            ConceptType c = o as ConceptType;

            // Prepare row value list
            List<string> rowValues = new List<string>(header.Columns.Count);
            rowValues.Add(c.Id);
            rowValues.Add(c.Parent);
            rowValues.Add(GetLevelOfCode(cScheme, c.Id).ToString());

            foreach (string lg in LangSupport.SupportedLanguages)
            {
                rowValues.Add(c.Name.GetForLanguage(lg));
            }

            foreach (string lg in LangSupport.SupportedLanguages)
            {
                rowValues.Add(c.Description.GetForLanguage(lg));
            }

            // Annotations
            AddAnnotations(rowValues, c.AnnotationList);

            return rowValues;
        }

        private int GetLevelOfCode(ConceptSchemeType cs, string code)
        {
            int level = 0;
            ConceptType c = cs.ConceptList.LocateItem(code) as ConceptType;
            do
            {
                if (c != null)
                {
                    ++level;
                    c = cs.ConceptList.LocateItem(c.Parent) as ConceptType;
                }
            } while (c != null);

            return level;
        }

   }
}
